package com.heima.article.service.impl;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.article.mapper.ApArticleConfigMapper;
import com.heima.article.mapper.ApArticleContentMapper;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.mapper.ApCollectionMapper;
import com.heima.article.service.ApArticleService;
import com.heima.article.service.FreemarkerService;
import com.heima.common.exception.CustomException;
import com.heima.model.common.dtos.*;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.common.pojos.article.ApArticle;
import com.heima.model.common.pojos.article.ApArticleConfig;
import com.heima.model.common.pojos.article.ApArticleContent;
import com.heima.model.common.pojos.article.ApCollection;
import com.heima.model.common.vo.ArticleInfoVo;
import com.heima.model.common.vo.WmStatisticsPageVo;
import com.heima.utils.thread.ApThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author 陈辉
 * @data 2024 9:50
 */
@Service
@Slf4j
public class ApArticleServiceImpl extends ServiceImpl<ApArticleMapper, ApArticle> implements ApArticleService {

    @Autowired
    private ApArticleMapper apArticleMapper;
    @Autowired
    private ApArticleConfigMapper apArticleConfigMapper;
    @Autowired
    private ApArticleContentMapper apArticleContentMapper;
    @Autowired
    private FreemarkerService freemarkerService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private ApCollectionMapper apCollectionMapper;

    /**
     * 加载文章信息
     *
     * @param homeDto 查询条件
     * @param type    1：加载更多 2：加载更新
     * @return
     */
    @Override
    public ResponseResult load(ArticleHomeDto homeDto, int type) {
        //1. 参数校验
        if (homeDto == null || (type != 1 && type != 2)) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }

        //2. 数据处理
        if (homeDto.getMaxBehotTime() == null) homeDto.setMaxBehotTime(new Date());
        if (homeDto.getMinBehotTime() == null) homeDto.setMinBehotTime(new Date());
        if (homeDto.getSize() < 1 || homeDto.getSize() > 50) homeDto.setSize(10);

        //3. 调用mapper查询对应数据
        List<ApArticle> res = apArticleMapper.load(homeDto, type);

        //4. 封装结果返回
        return ResponseResult.okResult(res);
    }

    /**
     * 保存或修改文章信息
     *
     * @param articleDto
     * @return
     */
    @Override
    public ResponseResult saveOrUpdateArticle(ArticleDto articleDto) {
        //1. 同步自媒体文章信息
        if (articleDto.getId() == null) {
            //保存
            //1. 保存文章基本信息：ap_article
            ApArticle apArticle = new ApArticle();
            BeanUtils.copyProperties(articleDto, apArticle);
            apArticleMapper.insert(apArticle);
            articleDto.setId(apArticle.getId());

            //2. 创建文章默认配置：ap_article_config
            ApArticleConfig config = new ApArticleConfig(apArticle.getId());
            apArticleConfigMapper.insert(config);

            //3. 保存文章内容信息：ap_article_content
            ApArticleContent content = new ApArticleContent();
            content.setArticleId(apArticle.getId());
            content.setContent(articleDto.getContent());
            apArticleContentMapper.insert(content);
        } else {
            //修改
            //1. 修改文章基本信息：ap_article
            ApArticle apArticle = new ApArticle();
            BeanUtils.copyProperties(articleDto, apArticle);
            apArticleMapper.updateById(apArticle);

            //2. 修改文章内容信息：ap_article_content
            ApArticleContent content = new ApArticleContent();
            content.setArticleId(apArticle.getId());
            content.setContent(articleDto.getContent());
            //update ap_article_content set ? ,? where article_id = ?
            apArticleContentMapper.update(content,
                    Wrappers.<ApArticleContent>lambdaUpdate().eq(ApArticleContent::getArticleId, content.getArticleId()));
        }

        //2. 采用异步调用，提升当前接口的性能，生成文章详情页： freemarker + minio

        freemarkerService.generateDetailHtml(articleDto);


        //将文章id返回
        return ResponseResult.okResult(String.valueOf(articleDto.getId()));
    }


    /**
     * 文章上下架
     * <p>
     * is_down: 0: 上架， 1：下架
     *
     * @param map enable 0：下架， 1：上架
     */
    @Override
    public void downOrUp(Map map) {
        boolean isDown = true;            // 假设要下架

        if ((int) map.get("enable") == 1) {
            isDown = false;
        }
        ApArticleConfig config = new ApArticleConfig();
        config.setArticleId((long) map.get("article_id"));
        //update ap_article_config set is_down = ? where article_id = ?
        apArticleConfigMapper.update(config, Wrappers.<ApArticleConfig>lambdaUpdate()
                .set(ApArticleConfig::getIsDown, isDown)
                .eq(ApArticleConfig::getArticleId, config.getArticleId()));

    }

    /**
     * 评论状态
     *
     * @param commentStatus
     * @return
     */
    @Override
    public ResponseResult CommentStatus(CommentStatus commentStatus) {
        ApArticleConfig apArticleConfig = new ApArticleConfig();
        apArticleConfig.setArticleId(commentStatus.getArticleId().longValue());
        boolean flag;
        if (commentStatus.getOperation() == 1) {
            flag = true;
        } else if (commentStatus.getOperation() == 0) {
            flag = false;


        }

        return null;
    }

    @Override
    public ResponseResult articlesele(List<Long> entryIds) {
        //查询所有文章数据
        //根据id集合查询文章数据

        List<ApArticle> apArticles = apArticleMapper.selectBatchIds(entryIds);
        List<Lpinglunzhuangtai> list = new ArrayList<>();
        for (ApArticle apArticle : apArticles) {
            //根据apArticleId查询文章配置
            ApArticleConfig apArticleConfig = apArticleConfigMapper.selectById(apArticle.getId());
            Lpinglunzhuangtai lpinglunzhuangtai = new Lpinglunzhuangtai();
            lpinglunzhuangtai.setArticleId(apArticle.getId());
            if (apArticleConfig == null) {
                lpinglunzhuangtai.setIsComment(true);
            } else {
                lpinglunzhuangtai.setIsComment(apArticleConfig.getIsComment());
            }

            lpinglunzhuangtai.setTitle(apArticle.getTitle());
            lpinglunzhuangtai.setComments(apArticle.getComment());
            lpinglunzhuangtai.setUserId(apArticle.getAuthorId());
            list.add(lpinglunzhuangtai);


        }
        return ResponseResult.okResult(list);
    }

    @Override
    public List<ApArticle> getArticle(Integer userId, Date end, Date begin) {
        //查询 符合 Integer userId, Date end, Date begin条件的 ApArticle
        QueryWrapper<ApArticle> queryWrapper = new QueryWrapper<>();

        // 添加查询条件
        queryWrapper.eq("author_id", userId.longValue()) // userId
                .ge("publish_time", begin) // 大于等于开始时间
                .le("publish_time", end); // 小于等于结束时间
        List<ApArticle> apArticles = apArticleMapper.selectList(queryWrapper);


        return apArticles;
    }

    @Override
    public ApArticleConfig getConfig(Long id) {
        //查询符合articleId的数据
        QueryWrapper<ApArticleConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("article_id", id);
        ApArticleConfig apArticleConfig = apArticleConfigMapper.selectOne(queryWrapper);

        return apArticleConfig;
    }

    /**
     * 根据文章id查询文章信息
     *
     * @param articleDto
     * @return ApArticle
     */
    @Override
    public ResponseResult findId(ArticleDto articleDto) {
        ApArticle article = apArticleMapper.findId(articleDto);
        return ResponseResult.okResult(article);
    }

    /**
     * 更新文章阅读数据
     *
     * @param behaviorDto
     * @return
     */
    @Override
    public ResponseResult updateArticle(ReadBehaviorDto behaviorDto) {
        //数据校验
        if (behaviorDto == null || behaviorDto.getArticleId() == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        //验证userid
        if (StringUtils.isEmpty(behaviorDto.getUserId())) {
            throw new CustomException(AppHttpCodeEnum.NEED_LOGIN);
        }
        //判断当前文章是否存在
        LambdaQueryWrapper<ApArticle> wrapper = Wrappers.lambdaQuery(ApArticle.class)
                .eq(ApArticle::getId, behaviorDto.getArticleId());
        ApArticle article = getOne(wrapper);
        if (article == null) {
            //不存在当前文章
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //更新次数
        LambdaUpdateWrapper<ApArticle> updateWrapper = Wrappers.lambdaUpdate(ApArticle.class)
                .set(ApArticle::getViews, article.getViews() == null ? behaviorDto.getCount() : article.getViews() + 1)
                .eq(ApArticle::getId, behaviorDto.getArticleId());
        update(updateWrapper);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 加载文章行为-数据回显
     *
     * @param articleInfoDto
     * @return
     */
    @Override
    public ResponseResult loadBehavior(ArticleInfoDto articleInfoDto) {
        //参数校验
        if (articleInfoDto == null || articleInfoDto.getArticleId() == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        //获取当前用户id
        Integer userId = ApThreadLocalUtil.get();
        //创建VO
        ArticleInfoVo articleInfoVo = new ArticleInfoVo();
        //1判断当前用户**是否已经关注该文章的作者
        String followKey = "ATTENTION_" + articleInfoDto.getAuthorId();
        if (redisTemplate.hasKey(followKey)) {
            articleInfoVo.setIsfollow(true);
        } else {

            articleInfoVo.setIsfollow(false);
        }
        // 2是否收藏了此文章
        //先查询redis
        String collectionKey = "collection_" + userId + "_" + articleInfoDto.getArticleId();
        if (redisTemplate.hasKey(collectionKey)) {
            articleInfoVo.setIscollection(true);
        } else {
            //查询数据库
            ApCollection apCollection = apCollectionMapper.selectOne(new LambdaQueryWrapper<ApCollection>()
                    .eq(ApCollection::getEntryId, userId)
                    .eq(ApCollection::getArticleId, articleInfoDto.getArticleId()));
            //数据库查询不到则为false 查到为true
            if (apCollection == null) {
                articleInfoVo.setIscollection(false);
            } else {
                articleInfoVo.setIscollection(true);
            }
        }
        //3 是否点赞了文章
        //3.1从redis找到对应的数据
        String likeKey = "like_" + userId + "_" + articleInfoDto.getArticleId();
        if (redisTemplate.hasKey(likeKey)) {
            //存在
            articleInfoVo.setIslike(true);
        } else {
            articleInfoVo.setIslike(false);
        }
        //4 是否不喜欢该文章等
        //4.1从redis找到对应的数据
        String unLikeKey = "unLike_" + userId + "_" + articleInfoDto.getArticleId();
        if (redisTemplate.hasKey(unLikeKey)) {
            //存在
            articleInfoVo.setIsunlike(true);
        } else {
            articleInfoVo.setIsunlike(false);
        }
        return ResponseResult.okResult(articleInfoVo);
    }

    /**
     * 更新文章评论状态
     *
     * @param commentStatus
     * @return
     */
    @Override
    public ResponseResult updateStatus(CommentStatus commentStatus) {
        ApArticleConfig apArticleConfig = new ApArticleConfig();
        apArticleConfig.setArticleId(commentStatus.getArticleId());
        if (commentStatus.getOperation() == 1) {
            apArticleConfig.setIsComment(true);
        } else if (commentStatus.getOperation() == 0) {
            apArticleConfig.setIsComment(false);
        }
        //修改ApArticleConfig 判断条件为符合 ArticleId

        apArticleConfigMapper.update(apArticleConfig, new QueryWrapper<ApArticleConfig>().eq("article_id", commentStatus.getArticleId()));


        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public Page<ApArticle> getArticle2(Integer userId, Date end, Date begin, FindNewsDto findNewsDto) {
        //进行分页查询
        Page<ApArticle> page = new Page<>(findNewsDto.getPage(), findNewsDto.getSize());

        //查询当前用户
        QueryWrapper<ApArticle> wrapper = new QueryWrapper<>();
        wrapper.eq("author_id", userId.longValue());
        wrapper.ge("publish_time", begin);
        wrapper.le("publish_time", end);
        wrapper.orderByDesc("publish_time");
        return apArticleMapper.selectPage(page, wrapper);

    }

    /**
     * 查询用户id
     *
     * @param
     * @return
     */
    @Override
    public ResponseResult getArticleList(String beginDate, String endDate, Integer userId) {
        // 单独进行查询
        LambdaQueryWrapper<ApArticle> between = Wrappers.lambdaQuery(ApArticle.class)
                .eq(ApArticle::getAuthorId, userId)
                .between((beginDate != null && endDate != null),
                        ApArticle::getCreatedTime,
                        beginDate,
                        endDate)
                .orderByDesc(ApArticle::getCreatedTime);
        List<ApArticle> list = list(between);
        return ResponseResult.okResult(list);
    }

    /**
     * 进行分页查询
     *
     * @param beginDate
     * @param endDate
     * @param page
     * @param pageSize
     * @param userId
     * @return
     */
    @Override
    public ResponseResult getPage(String beginDate, String endDate, Integer page, Integer pageSize, Integer userId) {
        if (page < 0) {
            page = 1;
        }
        if (pageSize < 0 || pageSize > 50) {
            pageSize = 10;
        }
        // 单独进行查询
        LambdaQueryWrapper<ApArticle> query = Wrappers.lambdaQuery(ApArticle.class)
                .eq(ApArticle::getAuthorId, userId)
                .between((beginDate != null && endDate != null),
                        ApArticle::getCreatedTime,
                        beginDate,
                        endDate)
                .orderByDesc(ApArticle::getCreatedTime);
        Page pageRes = new Page(page, pageSize);
        page(pageRes, query);
        PageResponseResult result = new PageResponseResult(
                (int) pageRes.getCurrent(),
                (int) pageRes.getSize(),
                (int) pageRes.getTotal()
        );
        List records = pageRes.getRecords();
        //创建一个几个存储数据
        List<WmStatisticsPageVo> pageVoList = new ArrayList<>();
        records.forEach(record -> {
            WmStatisticsPageVo wmStatisticsPageVo = new WmStatisticsPageVo();
            BeanUtils.copyProperties(record, wmStatisticsPageVo);
            if (wmStatisticsPageVo.getComment() == null) {
                wmStatisticsPageVo.setComment(0);
            }
            if (wmStatisticsPageVo.getLikes() == null) {
                wmStatisticsPageVo.setLikes(0);
            }
            if (wmStatisticsPageVo.getViews() == null) {
                wmStatisticsPageVo.setViews(0);
            }
            if (wmStatisticsPageVo.getCollection() == null) {
                wmStatisticsPageVo.setCollection(0);
            }
            pageVoList.add(wmStatisticsPageVo);
        });
        result.setData(pageVoList);
        return result;
    }

    /**
     * 更新文章收藏
     *
     * @param behaviorDto
     * @return
     */
    @Override
    public ResponseResult updateCollection(CollectionBehaviorDto behaviorDto) {
        //参数校验
        if (behaviorDto == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        //创建ApCollection
        ApCollection apCollection = new ApCollection();
        //文章id
        apCollection.setArticleId(behaviorDto.getEntryId());
        //发布时间
        apCollection.setPublishedTime(behaviorDto.getPublishedTime());
        //类型
        apCollection.setType(behaviorDto.getType());

        //用户id
        Integer userId = ApThreadLocalUtil.get();
        apCollection.setEntryId(userId);
        //创建时间
        apCollection.setCollectionTime(new Date());

        log.info("apCollection的数据为：{}",apCollection);

        //根据文章id和用户id查询 查询库中 是否存在对应的数据
        QueryWrapper<ApCollection> queryWrapper = new QueryWrapper<>();
        QueryWrapper<ApCollection> eq = queryWrapper.eq("article_id", behaviorDto.getEntryId()).eq("entry_id", userId);
        //根据文章id查询 ap_article表 对应的 文章数据
        ApArticle apArticle = apArticleMapper.selectById(behaviorDto.getEntryId());
        //用户文章收藏
        ApCollection apCollection1 = apCollectionMapper.selectOne(eq);

        String key = "collection_" + userId + "_" + behaviorDto.getEntryId();
        //查询redis 判断是否存在对应的数据
        if (redisTemplate.hasKey(key)) {
            //存在
            //判断 是收藏 还是取消收藏
            if (behaviorDto.getOperation() == 0) {
                //收藏
                redisTemplate.opsForValue().set(key, String.valueOf(behaviorDto.getOperation()));
            } else if (behaviorDto.getOperation() == 1) {
                //取消收藏
                redisTemplate.delete(key);
            }
        } else {
            //查数据库
            //判断是收藏还是取消收藏
            if (behaviorDto.getOperation() == 0) {
                //收藏
                if (apCollection1 == null) {
                    //存在
                    //更新文章收藏数+1
                    apArticle.setCollection(apArticle.getCollection() == null ? 0 : apArticle.getCollection() + 1);
                    //存关系
                    apCollectionMapper.insert(apCollection);
                    //  添加redis
                    redisTemplate.opsForValue().set(key, String.valueOf(behaviorDto.getOperation()));
                }else {
                    return ResponseResult.errorResult(AppHttpCodeEnum.ALREADY_COLLECT_ERROR);
                }
            } else if (behaviorDto.getOperation() == 1) {
                //取消收藏
                if (apCollection1 != null) {
                    //存在
                    //删除用户收藏关系
                    apCollectionMapper.delete(eq);
                    //更新文章收藏数-1
                    apArticle.setCollection(apArticle.getCollection() == null ? 0 : apArticle.getCollection() - 1);
                }else {
                    return ResponseResult.errorResult(AppHttpCodeEnum.ALREADY_COLLECT_ERROR);
                }
            }
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }


}
